package pers.yurwisher.rubick.oauth2.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import pers.yurwisher.rubick.common.utils.PudgeUtil;
import pers.yurwisher.rubick.oauth2.filter.IgnoreLogoutFilter;

/**
 * @author yq 2021/4/15 11:49
 * @description WebSecurityConfig  security web安全配置,spring-cloud-starter-oauth2依赖于security
 * 默认情况下SecurityConfigurerAdapter执行比ResourceServerConfig先
 */
@Configuration
@EnableWebSecurity
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private IgnoreLogoutFilter ignoreLogoutFilter;

    @Bean
    public PasswordEncoder passwordEncoder() {
        log.info("初始化 PasswordEncoder");
        // 密码加密方式
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
                return PudgeUtil.encodePwd(charSequence.toString());
            }

            @Override
            public boolean matches(CharSequence charSequence, String encodedPassword) {
                return encodedPassword.equals(PudgeUtil.encodePwd(charSequence.toString()));
            }
        };
    }

    /**
     * 为了实现 OAuth2 的 password 模式必须要指定的授权管理 Bean
     *
     * @return 授权管理 Bean
     * @throws Exception 异常
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/css/**", "/static/**");
    }

    /**
     * 安全请求配置,这里配置的是security的部分，这里配置全部通过，安全拦截在资源服务的配置文件中配置，
     * 要不然访问未验证的接口将重定向到登录页面，前后端分离的情况下这样并不友好，无权访问接口返回相关错误信息即可
     *
     * @param http 请求
     * @throws Exception 异常
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //所有请求都需要认证
        http
                .formLogin().loginPage("/login").permitAll()
                .and().authorizeRequests().anyRequest().permitAll()
                // 禁用 CSRF CORS
                .and().csrf().disable().cors()
                //防止iframe 造成跨域
                .and().headers().frameOptions().disable()
                // 授权码模式通过session来完成 不可开启此项
//                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                //logout请求直接转发
                .and().addFilterBefore(ignoreLogoutFilter, LogoutFilter.class);
    }

    public static void main(String[] args) {
        System.out.println(PudgeUtil.encodePwd("123456"));
    }
}
